/*
 *	ME2 C++ SDK
 *	Copyright (c) 2010 _silencer
 *
 *	Permission is hereby granted, free of charge, to any person
 *	obtaining a copy of this software and associated documentation
 *	files (the "Software"), to deal in the Software without
 *	restriction, including without limitation the rights to use,
 *	copy, modify, merge, publish, distribute, sublicense, and/or sell
 *	copies of the Software, and to permit persons to whom the
 *	Software is furnished to do so, subject to the following
 *	conditions:
 *
 *	The above copyright notice and this permission notice shall be
 *	included in all copies or substantial portions of the Software.
 *
 *	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 *	OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 *	NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 *	HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 *	WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 *	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *	OTHER DEALINGS IN THE SOFTWARE.
 */

#ifndef UNREAL_TEMPLATES_H
#define UNREAL_TEMPLATES_H

#include "unreal_core.h"

namespace unreal
{
	#pragma pack(push)
	#pragma pack(1)

	/*
		TODO if we get dynamic memory working this template could be improved!
	 */
	template <typename _T>
	class uarray
	{
	public:

		typedef uarray<_T> type;
		typedef const type const_type;
		typedef type* this_type;

		_T& operator[]( const uint32 index )
		{
			return data_[index];
		}

		_T& at( const uint32 index )
		{
			return data_[index];
		}

		type& operator=( const_type& other )
		{
			//Should be able to release buffer! Need dynamic memory support from engine!
			//if ( data_ )
			//	uengine_free( data_ );

			data_ = other.data_;
			size_ = other.size_;
			reserved_size_ = other.reserved_size_;

			return this*;
		}

		bool operator==( const_type& other ) const
		{
			if ( size_ != other.size_ )
				return false;

			return ::memcmp( data_, other.data_, size_ ) == 0;
		}

		bool operator!=( const_type& other ) const
		{
			if ( size_ != other.size_ )
				return true;

			return ::strcmp( data_, other.data_, size_ ) != 0;
		}

		bool is_valid( const uint32 index ) const
		{
			return ( index >= 0 ) && ( index < size_ );
		}

		bool is_empty() const
		{
			return ( size_ == 0 );
		}

		uint32 size() const
		{
			return size_;
		}

		uint32 reserved_size() const
		{
			return reserved_size_;
		}

	protected:

		_T* data_;
		uint32 size_;
		uint32 reserved_size_;
	};

	/*
		TODO should have read only access! Perhaps later even adding new values...
	 */
	template <typename _key, typename _value>
	class umap
	{
	public:

		struct umap_pair
		{
			uint32 hash_next;
			_key key;
			uint32 unknown;
			_value value;
		};

		typedef umap<_key, _value> type;
		typedef const type const_type;
		typedef type* this_type;

		/*_value& operator[]( const _key& key )
		{
			return ;
		}*/

	protected:

		uarray<umap_pair> pairs_;
		uint32* hash_;
		uint32 hash_count_;
	};

	#pragma pack(pop)
}

#endif
